package com.arrogames.rgblabyrinth.game {
	import com.arrogames.lib.ash.animation.AnimationSystem;
	import com.arrogames.lib.ash.movement.MovementSystem;
	import com.arrogames.rgblabyrinth.game.debug.DebugSystem;
	import com.arrogames.rgblabyrinth.game.lighting.LightRenderingSystem;
	import com.arrogames.rgblabyrinth.game.rendering.TileRenderingSystem;
	import com.arrogames.rgblabyrinth.game.targeting.TargetingSystem;
	import com.arrogames.rgblabyrinth.game.trigger.TriggerSystem;
	import com.arrogames.rgblabyrinth.game.ui.GamePanel;
	
	import ash.core.Engine;
	import ash.core.System;
	import ash.integration.starling.StarlingFrameTickProvider;
	
	import starling.core.Starling;

	public class GameEngine extends Engine {
		private var creator:EntityCreator;
		
		private var tickProvider:StarlingFrameTickProvider;
		private var started:Boolean;

		//the view for the game
		private var gamePanel:GamePanel;
		private var mapDependentSystems:Vector.<System>;
		
		public function GameEngine(gamePanel:GamePanel) {
			this.gamePanel = gamePanel;
			tickProvider = new StarlingFrameTickProvider( Starling.current.juggler );
			mapDependentSystems = new Vector.<System>();
			
			creator = new EntityCreator(this);
			setupInitialSystems();
		}
		
		public function start() : void {
			started = true;
			tickProvider.add( this.update );
			tickProvider.start();
		}
		
		public function stop():void {
			tickProvider.stop();
			started = false;
			cleanUpLingeringSystems();
			removeAllEntities();
		}
		
		public function loadLevel():void {
			if (!started) {
				cleanUpLingeringSystems();
				
				var level:LevelLoader = new LevelLoader(creator);
				creator.createGameState(level.map);
				
				_addSystem( new TargetingSystem(gamePanel.gameContent), 16);
				_addSystem(new LightRenderingSystem(gamePanel.lightLayer, level.map), 19);
				_addSystem(new TileRenderingSystem(gamePanel.gameContent, level.map), 20);
				var debugSystem:DebugSystem = _addSystem(new DebugSystem(gamePanel.gameContent, level.map), 20) as DebugSystem;
				
				creator.createTiledWorld(level.map);
				level.loadObjectsTmx();
				debugSystem.drawGrid();
			} else {
				throw new Error("Can't update level if game engine is started!");
			}
		}
		
		private function _addSystem(system:System, priority:int):System {
			mapDependentSystems.push(system);
			addSystem(system, priority);
			return system;
		}
		
		private function setupInitialSystems():void {
			addSystem( new MovementSystem(), 15);
			addSystem( new TriggerSystem(creator), 16);
			addSystem( new AnimationSystem(), 19);
		}
		
		private function cleanUpLingeringSystems():void {
			for (var i:int = 0; i < mapDependentSystems.length; i++) {
				removeSystem(mapDependentSystems[i] as System);
			}
			mapDependentSystems.length = 0;
		}
		
		public function get isPaused():Boolean { return started && !tickProvider.playing; }
		public function set isPaused(value:Boolean):void {
			if (value) {
				tickProvider.stop();
			} else {
				tickProvider.start();
			}
		}
	}
}